/**
 * OSAmI: Open Source Ambient Intelligence
 * A simple publish/subscribe/dispatch API (based on multicast communications) for constrained devices.
 * Copyright (C) Lionel Debroux 2006 (as a TER/Magistere M1 student in the LSR-IMAG-ADELE team, for a demo in the H-Omega project)
 * Copyright (C) Lionel Debroux 2010 (as an engineer in the LCIS-INPG-CTSYS team, for a pre-demo in the FR part of the OSAMI project)
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
 */

package fr.imag.adele.homega.impl.multicast;

import java.net.InetAddress;

/**
 * This class parses messages upon reception.
 * The work is done by the constructor.
 * Keep InboundMessage and OutboundMessage in sync !
 */
public class InboundMessage implements Message {

	private InetAddress from;
	private int portnr;
	private InetAddress to;
	private String message;

	/**
	 * Parse given string into originator address, to address, port number and payload.
	 */
	public InboundMessage(String data) throws Exception {
		int place;
		String port;
		String newdata = new String(data);

		newdata.trim();

		// Message header
		if (!newdata.startsWith(MESSAGE_PROTOCOL_VERSION)) {
			throw new Exception("InboundMessage: malformed message !");
		}
		newdata = newdata.substring(MESSAGE_PROTOCOL_VERSION.length());


		// Next separator
		place = newdata.indexOf(MESSAGE_FIELD_SEPARATOR);
		if (place == -1) {
			throw new Exception("InboundMessage: malformed message !");
		}


		// Sender
		from = InetAddress.getByName(newdata.substring(0, place));
		newdata = newdata.substring(place+MESSAGE_FIELD_SEPARATOR.length());
		if (!(from.isMulticastAddress())) {
			throw new Exception("InboundMessage: sender is not a multicast address !");
		}


		// Next separator
		place = newdata.indexOf(MESSAGE_FIELD_SEPARATOR);
		if (place == -1) {
			throw new Exception("InboundMessage: malformed message !");
		}


		// Receiver
		to = InetAddress.getByName(newdata.substring(0, place));
		newdata = newdata.substring(place+MESSAGE_FIELD_SEPARATOR.length());
		if (!(to.isMulticastAddress())) {
			throw new Exception("InboundMessage: Receiver is not a multicast address !");
		}


		// Next separator
		place = newdata.indexOf(MESSAGE_FIELD_SEPARATOR);
		if (place == -1) {
			throw new Exception("InboundMessage: malformed message !");
		}


		// Port
		port = newdata.substring(0, place);
		newdata = newdata.substring(place+MESSAGE_FIELD_SEPARATOR.length());
		portnr = Integer.parseInt(port);


		// Wrapper before payload
		if (!(newdata.startsWith(MESSAGE_WRAPPER))) {
			throw new Exception("InboundMessage: malformed message !");
		}


		// Strip trailing 0x00 characters.
		place = newdata.indexOf(0);
		if (place != -1) {
			newdata = newdata.substring(MESSAGE_WRAPPER.length(),place);
		}
		else {
			newdata = newdata.substring(MESSAGE_WRAPPER.length());
		}


		// Wrapper after payload
		if (!(newdata.endsWith(MESSAGE_WRAPPER))) {
			throw new Exception("InboundMessage: malformed message !");
		}


		// Payload
		message = newdata.substring(0,newdata.length()-MESSAGE_WRAPPER.length());
	}

	public String toString() {
		return message;
	}

	// Getters, setters.
	public String getMessage() {
		return message;
	}

	public int getPortnr() {
		return portnr;
	}

	public InetAddress getTo() {
		return to;
	}

	/*public void setMessage(String message) {
		this.message = message;
	}*/

	/*public void setPortnr(int portnr) {
		this.portnr = portnr;
	}*/

	/*public void setTo(InetAddress to) {
		this.to = to;
	}*/
}
